package ar.com.cooker.spider.ut;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import ar.com.cooker.spider.SpiderException;

public class XPathUt {

	private Document doc = null;
	private XPath xpath = null;

	public XPathUt(InputStream is) throws SpiderException{
		
	    DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
	    domFactory.setValidating(false);
						
	    xpath = XPathFactory.newInstance().newXPath();
	    domFactory.setNamespaceAware(true); 
	    DocumentBuilder builder = null;
		try {
			builder = domFactory.newDocumentBuilder();
			builder.setEntityResolver(new EntityResolver() {
			        @Override
			        public InputSource resolveEntity(String publicId, String systemId)
			                throws SAXException, IOException {
			            if (systemId.contains("xhtml1-transitional.dtd")) {			            	
//			            	 InputStream dtdStream = EntityResolver.class.getResourceAsStream("dtds/xhtml1-transitional.dtd");			            	 
//			            	 return new InputSource(dtdStream);
			            	  return new InputSource(new StringReader(""));
			            	 
			            } else {
			                return null;
			            }
			        }
			    });
			
		} catch (ParserConfigurationException e) {
			throw new SpiderException("Imposible crear documento nuevo en clase: "+this.getClass().toString()+". Motivo: "+e.getCause(),e);
		}
	    //Document doc = builder.parse("persons.xml");
		try {			
			doc = builder.parse(is);
		} catch (Exception e) {
			e.printStackTrace();
			throw new SpiderException("Imposible parsear input stream en clase: "+this.getClass().toString()+". Motivo: "+e.getCause(),e);
		}
	}
	
	
	
  public  List<String> getValue(String xpathExpression)  throws SpiderException {
	  return parseGeneric(xpathExpression,null);
  }
  
  public  List<String> getAttribute(String xpathExpression,String attName)  throws SpiderException {
	  return parseGeneric(xpathExpression,attName);
  }
  
  private List<String> parseGeneric(String xpathExpression,String attName) throws SpiderException {

	List<String> list = new ArrayList<String>();
   
    XPathExpression expr = null;
	try {
		expr = xpath.compile(xpathExpression);
	} catch (XPathExpressionException e) {
		throw new SpiderException("Imposible compilar Xpath Expression en clase: "+this.getClass().toString()+". Motivo: "+e.getCause(),e);
	}
    Object result = null;
	try {
		result = expr.evaluate(doc, XPathConstants.NODESET);
	} catch (XPathExpressionException e) {
		throw new SpiderException("Imposible evaluar documento en clase: "+this.getClass().toString()+". Motivo: "+e.getCause(),e);

	}
    NodeList nodes = (NodeList) result;    
    for (int i = 0; i < nodes.getLength(); i++) {
    	if(attName==null){
	    	if(nodes.item(i).getNodeValue()!=null)
	    		list.add(nodes.item(i).getNodeValue());	    	
    	}else{
    		if(nodes.item(i).getAttributes()!=null && nodes.item(i).getAttributes().getNamedItem(attName)!=null)	    			
	    		list.add(nodes.item(i).getAttributes().getNamedItem(attName).toString());
    	}
    }    
    return list;
  }
}